package health_system.health_system.service.impl;

import health_system.health_system.service.FileStorageService;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service;
import org.springframework.util.FileSystemUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.UUID;
import java.util.stream.Stream;

@Service
@Slf4j
public class FileStorageServiceImpl implements FileStorageService {
    @Value("${app.file-storage.base-dir:uploads}")
    private String baseDir;
    @Value("${app.file-storage.base-url:https://localhost:8443/files}")
    private String baseUrl;
    private Path rootLocation;
    @Override
    @PostConstruct
    public void init() {
        rootLocation = Paths.get(baseDir).toAbsolutePath().normalize();
        try {
            Files.createDirectories(rootLocation);
            Files.createDirectories(rootLocation.resolve("image"));
            Files.createDirectories(rootLocation.resolve("video"));
            Files.createDirectories(rootLocation.resolve("audio"));
            Files.createDirectories(rootLocation.resolve("file"));
            log.info("File storage initialized at: {}", rootLocation);
        } catch (IOException e) {
            log.error("Could not initialize file storage", e);
            throw new RuntimeException("Could not initialize file storage", e);
        }
    }
    @Override
    public String store(MultipartFile file, String directory) {
        try {
        if (file.isEmpty()) {
                throw new RuntimeException("Failed to store empty file");
        }
            // 创建子目录（如果不存在）
            Path targetDir = rootLocation;
            if (directory != null && !directory.isEmpty()) {
                targetDir = rootLocation.resolve(directory);
                Files.createDirectories(targetDir);
            }
            // 生成唯一文件名
            String uniqueFilename = generateUniqueFileName(file.getOriginalFilename());
            Path destinationFile = targetDir.resolve(uniqueFilename);
            
            // 将文件复制到目标位置，如果存在则替换
            Files.copy(file.getInputStream(), destinationFile, StandardCopyOption.REPLACE_EXISTING);
            
            String relativePath = directory == null ? uniqueFilename : directory + "/" + uniqueFilename;
            log.info("Stored file: {}", relativePath);
            
            return relativePath;
        } catch (IOException e) {
            throw new RuntimeException("Failed to store file", e);
        }
    }
    
    @Override
    public String storeMediaFile(byte[] fileData, String fileName, String mediaType) throws IOException {
        // 生成唯一文件名，避免文件名冲突
        String uniqueFileName = generateUniqueFileName(fileName);
        
        // 确保mediaType是有效的
        String validMediaType = validateMediaType(mediaType);
        
        // 构建文件路径
        String relativePath = validMediaType + "/" + uniqueFileName;
        Path filePath = rootLocation.resolve(relativePath);
        
        // 写入文件
        try (FileOutputStream fos = new FileOutputStream(filePath.toFile())) {
            fos.write(fileData);
        }
        
        log.info("Stored file: {} at path: {}", fileName, filePath);
        
        // 返回相对路径，用于数据库存储
        return relativePath;
    }
    
    @Override
    public Stream<Path> loadAll() {
        try {
            return Files.walk(this.rootLocation, 1)
                    .filter(path -> !path.equals(this.rootLocation))
                    .map(this.rootLocation::relativize);
        } catch (IOException e) {
            throw new RuntimeException("Failed to read stored files", e);
        }
    }
    
    @Override
    public Path load(String filename) {
        return rootLocation.resolve(filename);
    }
    
    @Override
    public Resource loadAsResource(String filename) {
        try {
            Path file = load(filename);
            Resource resource = new UrlResource(file.toUri());
            if (resource.exists() || resource.isReadable()) {
                return resource;
            } else {
                throw new RuntimeException("Could not read file: " + filename);
            }
        } catch (MalformedURLException e) {
            throw new RuntimeException("Could not read file: " + filename, e);
        }
    }
    
    @Override
    public boolean delete(String filename) {
        try {
            Path file = load(filename);
            return Files.deleteIfExists(file);
        } catch (IOException e) {
            log.error("Error deleting file: {}", filename, e);
            return false;
        }
    }
    
    @Override
    public String getFileUrl(String filePath) {
        return baseUrl + "/" + filePath;
    }
    
    @Override
    public boolean deleteFile(String filePath) {
        try {
            Path path = rootLocation.resolve(filePath);
            return Files.deleteIfExists(path);
        } catch (IOException e) {
            log.error("Failed to delete file: {}", filePath, e);
            return false;
        }
    }
    
    @Override
    public void deleteAll() {
        FileSystemUtils.deleteRecursively(rootLocation.toFile());
        log.info("All files deleted from storage at: {}", rootLocation);
    }
    
    @Override
    public String generateUniqueFileName(String originalFileName) {
        String fileExtension = "";
        if (originalFileName != null && originalFileName.contains(".")) {
            fileExtension = originalFileName.substring(originalFileName.lastIndexOf("."));
        }
        
        return UUID.randomUUID().toString() + fileExtension;
    }
    
    /**
     * 验证并标准化媒体类型
     */
    private String validateMediaType(String mediaType) {
        String type = mediaType.toLowerCase();
        
        if (!type.equals("image") && !type.equals("video") && 
            !type.equals("audio") && !type.equals("file")) {
            // 如果不是已知的媒体类型，默认为"file"
            return "file";
        }
        
        return type;
    }
} 